package cn.jbolt.ai.app.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.jbolt.ai.app.config.AppConfigConstant;
import cn.jbolt.ai.app.config.FuncCallNodeConfig;
import cn.jbolt.ai.app.config.KlbNodeConfig;
import cn.jbolt.ai.app.service.AiAppService;
import cn.jbolt.util.JSONUtil;
import cn.jbolt.util.CacheUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.jbolt.ai.app.dao.AiAppConfigMapper;
import cn.jbolt.ai.app.entity.AiAppConfig;
import cn.jbolt.ai.app.service.AiAppConfigService;
import cn.jbolt.util.Result;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class AiAppConfigServiceImpl extends ServiceImpl<AiAppConfigMapper, AiAppConfig> implements AiAppConfigService {

    private static final Logger logger = LoggerFactory.getLogger(AiAppConfigServiceImpl.class);
    @Autowired
    private AiAppService appService;


    @Override
    public Result add(String linkType, Long linkId, String configType, JsonNode configValue) {
        AiAppConfig configDb = new AiAppConfig();
        configDb.setLinkId(linkId);
        configDb.setLinkType(linkType);
        configDb.setConfigType(configType);
        configDb.setConfigValue(configValue.toString());
        boolean save = this.save(configDb);
        if (!save) {
            return Result.error("添加失败");
        }
        //移除之前的缓存
        CacheUtil.removeObject(CacheUtil.KEY_APP_CONFIG + "_" + linkType + "_" + linkId);
        //查询所有的缓存,存入
        getAllConfigByLinkId(linkType, linkId);
        return Result.success();
    }


    @Transactional
    public Result add(String linkType, Long linkId, JsonNode config) {
        Iterator<String> iterator = config.fieldNames();
        while (iterator.hasNext()) {
            String key = iterator.next();
            if (StrUtil.isNotEmpty(key)) {
                AiAppConfig configDb = new AiAppConfig();
                configDb.setLinkId(linkId);
                configDb.setLinkType(linkType);
                configDb.setConfigType(key);
                configDb.setConfigValue(config.get(key).toString());
                boolean save = this.save(configDb);
                if (!save) {
                    return Result.error("添加失败");
                }
            }
        }
        //移除之前的缓存
        CacheUtil.removeObject(CacheUtil.KEY_APP_CONFIG + "_" + linkType + "_" + linkId);
        //查询所有的缓存,存入
        getAllConfigByLinkId(linkType, linkId);
        return Result.success();
    }

    @Override
    public Result update(String linkType, Long linkId, String configType, String configValue) {
        AiAppConfig config = this.getOne(new QueryWrapper<AiAppConfig>().eq("link_id", linkId).
                eq("link_type", linkType).
                eq("config_type", configType));
        if (config != null) {
            config.setConfigValue(configValue);
            boolean b = this.updateById(config);
            if (b) {
                //移除缓存
                CacheUtil.removeObject(CacheUtil.KEY_APP_CONFIG + "_" + linkType + "_" + linkId);
                logger.info("缓存中appConfig移除成功:{}_{}_{}", CacheUtil.KEY_APP_CONFIG, linkType, linkId);
            }
        } else { //如果是null的话,就新建补上配置
            config = new AiAppConfig();
            config.setLinkId(linkId);
            config.setLinkType(linkType);
            config.setConfigType(configType);
            config.setConfigValue(configValue);
            this.save(config);
        }
        //添加到缓存
        JsonNode configJson = getAllConfigByLinkId(linkType, linkId);
        return Result.success(configJson);

    }

    @Override
    public Result delete(Long id) {
        boolean deleted = this.removeById(id);
        if (deleted) {
            return Result.success();
        } else {
            return Result.error("删除失败");
        }
    }


    @Override
    public JsonNode getNodeValidConfig(Long appId, Long sessionId, Long nodeId) {
        ObjectNode validConfig = JSONUtil.createObjectNode();
        //先取出app的配置
        QueryWrapper<AiAppConfig> query = new QueryWrapper<>();
        query.eq("link_id", appId);
        query.eq("link_type", AppConfigConstant.LINK_TYPE_APP);
        List<AiAppConfig> configs = this.list(query);
        for (AiAppConfig item : configs) {
            validConfig.put(item.getConfigType(), JSONUtil.toJsonObject(item.getConfigValue()));
        }

        //先取出node的配置,与app的合并
        query = new QueryWrapper<>();
        query.eq("link_id", nodeId);
        query.eq("link_type", AppConfigConstant.LINK_TYPE_NODE);

        configs = this.list(query);
        for (AiAppConfig item : configs) {
            JsonNode jsonNode = validConfig.get(item.getConfigType());
            if (jsonNode != null) {
                //session有同样的配置就覆盖掉 node自己的
                validConfig.put(item.getConfigType(), JSONUtil.merge(jsonNode, item.getConfigValue()));
            } else {
                validConfig.put(item.getConfigType(), JSONUtil.toJsonObject(item.getConfigValue()));
            }
        }


        //取出session的配置
        query = new QueryWrapper<>();
        query.eq("link_id", sessionId);
        query.eq("link_type", AppConfigConstant.LINK_TYPE_SESSION);
        configs = this.list(query);
        for (AiAppConfig item : configs) {
            JsonNode jsonNode = validConfig.get(item.getConfigType());
            if (jsonNode != null) {
                //session有同样的配置就覆盖掉 node自己的
                validConfig.put(item.getConfigType(), JSONUtil.merge(jsonNode, item.getConfigValue()));
            } else {
                validConfig.put(item.getConfigType(), JSONUtil.toJsonObject(item.getConfigValue()));
            }

        }
        return validConfig;
    }

    @Override
    public Result deleteAllConfigByLinkId(String linkType, Long linkId, String configType) {
        QueryWrapper<AiAppConfig> query = new QueryWrapper<>();
        query.eq("link_type", linkType);
        query.eq("link_id", linkId);
        query.eq("config_type", configType);
        if (this.list(query).size()>0) {
            boolean deleted = this.remove(query);
            if (deleted) {
                //移除缓存
                CacheUtil.removeObject(CacheUtil.KEY_APP_CONFIG + "_" + linkType + "_" + linkId);
                logger.info("缓存中appConfig移除成功:{}_{}_{}", CacheUtil.KEY_APP_CONFIG, linkType, linkId);
                return Result.success();
            }
            return Result.error("删除失败");
        }
        return Result.success();

    }

    @Override
    public Result deleteAllConfigByLinkType(String linkType, List<Long> linkId) {
        QueryWrapper<AiAppConfig> query = new QueryWrapper<>();
        query.eq("link_type", linkType);
        if (linkId != null && linkId.size() > 0) {
            query.in("link_id", linkId);
        }
        List<AiAppConfig> list = this.list();
        if (list != null && list.size() > 0) {
            for (AiAppConfig item : list) {
                CacheUtil.removeObject(CacheUtil.KEY_APP_CONFIG + "_" + item.getLinkType() + "_" + item.getLinkId());
                logger.info("缓存中appConfig移除成功:{}_{}_{}", CacheUtil.KEY_APP_CONFIG, item.getLinkType(), item.getLinkId());
            }
            boolean deleted = this.remove(query);
            if (!deleted) {
                return Result.error("删除失败");
            }
        }
        return Result.success();
    }

    @Override
    public JsonNode getAllConfigByLinkId(String linkType, Long linkId) {
        JsonNode cache = getCache(linkType, linkId);
        if (cache != null) {
            return cache;
        }
        QueryWrapper<AiAppConfig> query = new QueryWrapper<>();
        query.eq("link_id", linkId);
        query.eq("link_type", linkType);
        List<AiAppConfig> list = this.list(query);
        ObjectNode objectNode = JSONUtil.createObjectNode();
        for (AiAppConfig config : list) {
            String configType = config.getConfigType();  // 使用配置类型作为键，配置对象作为值
            objectNode.put(configType, JSONUtil.toJsonObject(config.getConfigValue()));
        }
        if (objectNode != null) {
            setCache(linkType, linkId, objectNode);
            return objectNode;
        } else {
            return null;
        }
    }

    @Override
    public Result getConfigByCondition(String linkType, Long linkId, String configType) {
        JsonNode allConfig = getAllConfigByLinkId(linkType, linkId);
        if (allConfig != null && allConfig.size() > 0) {
            JsonNode config = allConfig.get(configType);
            if (config != null) {
                return Result.success(config);
            }
        }
        return Result.success(null);
    }

    @Override
    public List<AiAppConfig> getObjectConfigByCondition(String linkType, Long linkId, String configType) {
        QueryWrapper<AiAppConfig> query = new QueryWrapper<>();
        query.eq("link_type", linkType);
        query.eq("link_id", linkId);
        query.eq("config_type", configType);
        List<AiAppConfig> list = this.list(query);
        return list;
    }

    @Override
    public Result delFuncConfigByFuncId(Long id) {
        QueryWrapper<AiAppConfig> query = new QueryWrapper<>();
        query.eq("link_type", AppConfigConstant.LINK_TYPE_APP).eq("config_type", AppConfigConstant.CONFIG_TYPE_FUNCCALL);
        query.like("config_value", id);
        List<AiAppConfig> configList = this.list(query);
        if (configList != null && configList.size() > 0) {
            for (AiAppConfig item : configList) {
                String configValue = item.getConfigValue();
                FuncCallNodeConfig nodeConfig = JSONUtil.toObject(configValue, FuncCallNodeConfig.class);
                if (nodeConfig != null) {
                    if (nodeConfig.getFunctions() != null && nodeConfig.getFunctions().length > 0) {
                        List<String> list = Arrays.asList(nodeConfig.getFunctions());
                        if (list.contains(id.toString())) { //找到id
                            list.remove(id.toString()); //移除
                            nodeConfig.setFunctions(list.toArray(new String[list.size()]));//更新新的
                            item.setConfigValue(JSONUtil.toJson(nodeConfig));
                            boolean b = this.updateById(item);
                            if (!b) {
                                return Result.error("删除失败");
                            }
                        }
                    }
                }


            }
        }
        return Result.success();

    }

    @Override
    public Result delConfigByKlbId(Long klbId) {
        QueryWrapper<AiAppConfig> query = new QueryWrapper<>();
        query.eq("link_type", AppConfigConstant.LINK_TYPE_APP).eq("config_type", AppConfigConstant.CONFIG_TYPE_KLB);
        query.like("config_value", klbId);
        List<AiAppConfig> configList = this.list(query);
        if (configList != null && configList.size() > 0) {
            for (AiAppConfig item : configList) {
                Long appId = item.getLinkId();
                Result result = appService.updateAppLinkCount(appId, AppConfigConstant.CONFIG_TYPE_KLB, 0);
                if (result.isError()) {
                    return Result.error("删除失败");
                }
                String configValue = item.getConfigValue();
                KlbNodeConfig nodeConfig = JSONUtil.toObject(configValue, KlbNodeConfig.class);
                if (nodeConfig != null) {
                    if (nodeConfig.getKlbId() != null) {
                        nodeConfig.setKlbId(null);
                        item.setConfigValue(JSONUtil.toJson(nodeConfig));
                        boolean b = this.updateById(item);
                        if (!b) {
                            return Result.error("删除失败");
                        }

                    }
                }


            }
        }
        return Result.success();

    }

    /**
     * 从缓存中获取appConfig
     *
     * @return
     */
    public JsonNode getCache(String linkType, Long linkId) {
        JsonNode cacheConfig = CacheUtil.getObject(CacheUtil.KEY_APP_CONFIG + "_" + linkType + "_" + linkId);
        logger.info("缓存中取出appConfig:{}_{}_{}-----{}:", CacheUtil.KEY_APP_CONFIG, linkType, linkId, cacheConfig);
        return cacheConfig;
    }

    /**
     * 把appConfig放入缓存
     *
     * @param config
     */
    public void setCache(String linkType, Long linkId, JsonNode config) {
        CacheUtil.putObject(CacheUtil.KEY_APP_CONFIG + "_" + linkType + "_" + linkId, config, -1, null);
        logger.info("appConfig存入缓存:{}_{}_{},已放入缓存,无过期时间-----{}:", CacheUtil.KEY_APP_CONFIG, linkType, linkId, config);
    }
}
